perm filename PAPERX.TEX[UHF,DEK] blob
sn#841766 filedate 1987-06-19 generic text, type C, neo UTF8
COMMENT ā VALID 00003 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 % Fonts for Digital Halftones, to be submitted to TUGboat: Addendum
C00005 00003 \pageno=25
C00013 ENDMK
Cā;
% Fonts for Digital Halftones, to be submitted to TUGboat: Addendum
% (this version assumes that \hsize=6.5in!)
\font\logo=manfnt \def\MF{{\logo META}\-{\logo FONT}}
\newif\ifaps % are we making copy for the APS?
%\apsfalse
\apstrue
\newcount\n
\def\tbox#1{\hidewidth\vbox to1.5em{\offinterlineskip\tilt
\vfil\expandafter\tb\number#1\empty\tb\vfil}\hidewidth}
\def\tb#1#2\tb{\ifx#1\empty\else\tb#2\tb\hbox{#1}\fi}
\def\mbox#1{$\vcenter{\kern-.2pt\hrule\kern-.2pt
\hbox to12pt{\kern-.2pt\vrule height 9pt depth 3pt\hss#1\hss\vrule\kern-.2pt}
\kern-.2pt\hrule\kern-.2pt}$}
\def\bbox{$\vcenter{\hbox to12pt{\vrule height 9pt width0pt depth 3pt\hss}
\kern-.2pt\hrule\kern-.2pt}$}
\def\lbox{$\vcenter{\hbox to12pt{\kern-.2pt\vrule height 9pt depth 3pt\hss}}$}
\chardef\other=12
\def\ttverbatim{\begingroup
\catcode`\\=\other \catcode`\{=\other \catcode`\}=\other
\catcode`\$=\other \catcode`\&=\other \catcode`\#=\other
\catcode`\%=\other \catcode`\~=\other \catcode`\ā=\other
\catcode`\_=\other
\obeyspaces \obeylines \tt}
{\obeyspaces\gdef {\ }}
\catcode`\|=\active \def|{\ttverbatim\let|=\endgroup}
\def\beginlines{\par\begingroup\nobreak\medskip\parindent=0pt \obeylines
\hrule\kern1pt\nobreak \everypar{\strut}}
\def\endlines{\kern1pt\hrule\endgroup\medbreak\noindent}
\pageno=25
\noindent\strut{\bf Addendum}
\vskip 1pt plus 1pt
\noindent Stop the presses! When I wrote the preceding pages (and had
them typeset), I was unaware of a ``well known'' method that should have
been included for comparison. So far this paper has considered
%\leftline{\bf Fonts for Digital Halftones: Addendum}
%\medskip
%\leftline{\indent Donald E. Knuth}
%\leftline{\indent Stanford University}
%\bigskip
%\noindent
%When I wrote the paper that appeared in {\sl TUGboat\/ \bf8}, 2 (July, 1987),
%999--999, I was unaware of an important method that should have been included
%for comparison. My paper considered
(1)~a halftone font with 65 levels of gray, in which each $8\times8$ character
essentially contributes two dots to a picture; and
(2)~a halftone font with 33 levels of gray, in which each $4\times8$ character
contributes one dot to a picture. It's also possible to construct (3)~a halftone
font with 17 levels of gray, in which each $4\times4$ character essentially
contributes half of a dot (actually two quarter-dots) to a picture. This
third method is based on an idea due to Robert L. Gard [{\sl Computer Graphics
and Image Processing\/ \bf5} (1976), 151--171].
The $k$th level of gray in the half-dot
scheme is obtained by blackening cells 0 to~$k-1$ in the array
$$\vcenter{\halign{&\mbox{#}\cr
1&5&10&14\cr
3&7&8&12\cr
13&9&6&2\cr
15&11&4&0\cr}}
\qquad \rm or \qquad
\vcenter{\halign{&\mbox{#}\cr
14&10&5&1\cr
12&8&7&3\cr
2&6&9&13\cr
0&4&11&15\cr}}\,\,.$$
(We actually make two sets of characters, one the mirror image of the other,
and alternate between them as a picture is typeset.)
The following \MF\ file will generate such a font |hd300|, in essentially the
%same way that the other fonts |dot300| and |hf300| were generated in my paper:
same way that the other fonts |dot300| and |hf300| were generated earlier:
\beginlines
|% halftone font with 17 levels of gray, characters "A" (white) to "Q" (black)|
|% includes also the mirror-reflected characters "a" (white) to "q" (black)|
\smallskip
|pair p[]; % the pixels in order (first p0 becomes black, then p1, etc.)|
|p0=(3,0); p4=(2,0); p8=(2,2); p12=(3,2);|
|transform r; r=identity rotatedaround ((1.5,1.5),180);|
\smallbreak
|for i=0 step 4 until 12: p[i+1]=p[i] transformed r;|
| p[i+2]=p[i] shifted (0,1); p[i+3]=p[i+2] transformed r; endfor|
\smallbreak
|w#:=4/pt; % that's 4 pixels|
|font_quad:=w#; designsize:=8w#;|
\smallbreak
|r:=identity reflectedabout ((2,0),(2,3));|
|picture prevchar; prevchar=nullpicture; % the pixels blackened so far|
|for i=0 upto 16:|
| beginchar(i+ASCII"A",w#,w#,0); currentpicture:=prevchar;|
| if i>0: addto currentpicture also unitpixel shifted p[i-1]; fi|
| prevchar:=currentpicture; endchar;|
| beginchar(i+ASCII"a",w#,w#,0);|
| currentpicture:=prevchar transformed r; endchar;|
| endfor|
\endlines
Here are four pictures for comparison, showing also the result of the elaborate
``dot diffusion'' method discussed at the end of my paper:
$$\vbox{\vbox to 44mm{}
\def\qbox#1{\hbox to.25\hsize{\hfil#1\hfil}}
\hbox{\qbox{double dot}\qbox{single dot}\qbox{half dot}\qbox{dot diffusion}}}$$
(Each of these was printed on a Canon laser printer with 300 pixels per inch.)
Gard's half-dot method clearly improves the quality of single-dot pictures;
it also has the advantage that its characters are square instead of diamond-shaped,
hence the data is easier to compute. On the other hand, it does require twice
as much data. Indeed, the double-dot picture shown here was typeset from
64 rows of 55 characters each; the single-dot picture was typeset from 128
rows of 55 characters each; and the half-dot picture was typeset from 128
rows of 110 characters each.
The upper left corner of the half-dot data for Mona Lisa looks like this:
\beginlines
|\beginhalftone|
|mMmMmLlLkKjJiIiIjJjJjJiIgGiJjJiGgGgIiIgGgGgGgGgIgFgGgGgGgFfFeFfFeGgGgGgGgGgFfFgIi| \dots
|LmMlLkKlLkJiIiHiIiJjJkJiGgIiIiGgFgGgGgGgGfFfGgFfEfFgFfFfGgEgGfEfGgGgGgGfFfFgGeGiH| \dots
|kKkKkKkKkJiIiHiIiIjJkKkJiIgGgFgIgFfFfFgGfEeEeEeEfGeGgGgHiJjJjIgGiGfGgGgFeFeGgFgGg| \dots
|JjJjKkKkKjIiGiIgGiJkJjJiIiIgGfGiGfEfEfGfFeEdEeDdEeFiKlMnNnNnNnMlKiGfFfFfFeFfFeFgG| \dots
|jJkJkKkLkJiHgGgGgIiJjJjIgGgFeFeGgGfEeEfEeDdDdEdDeJlNnOnOoOoOoOmOoNmKgEeDeEeEeDeEf| \dots
\endlines
Uppercase and lowercase letters alternate in a checkerboard fashion, so that
the reflected characters will appear in the correct positions. The |\beginhalftone|
macro is the same for half dots as for double dots; only the font name and the
data encoding scheme are different.
\bye